#include <gst/interfaces/xoverlay.h>
#include <gtk/gtk.h>

#ifdef GDK_WINDOWING_X11
#include <gdk/gdkx.h>  // for GDK_WINDOW_XID
#endif

gint
destroy(GtkWidget *widget,GdkEvent *event,gpointer data) {
	g_print("destroy\n");
	gtk_main_quit();
	return TRUE;
}

gboolean
bus_call(GstBus * bus, GstMessage *msg, gpointer data) {
	GtkWidget *window = (GtkWidget*) data;
	gchar *debug;
	GError *error;
	g_debug("bus_call %d",GST_MESSAGE_TYPE(msg));
	switch(GST_MESSAGE_TYPE(msg)) {
		case GST_MESSAGE_EOS:
			g_debug("end of stream");
			break;
		case GST_MESSAGE_ELEMENT:
			if (gst_structure_has_name(msg->structure, "prepare-xwindow-id")) {
				g_debug("prepare-xwindow-xid");
				gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(GST_MESSAGE_SRC(msg)), GDK_WINDOW_XID(gtk_widget_get_window(window)));
				return TRUE;
			}
			return FALSE;
			break;
		case GST_MESSAGE_ERROR :
			gst_message_parse_error(msg,&error,&debug);
			g_debug("error:%s debug:%s",error->message,debug);
			g_free(debug);
			g_error_free(error);
			gtk_main_quit();
			break;	
		default:
			break;
    }
	return TRUE;
}

GstElement *
create_pipeline(GtkWidget *area,gint width,gint height) {
	GstElement *pipeline,*source,*flip,*sink;
	GstCaps *caps;
	g_debug("create_pipeline");
	
	pipeline=gst_pipeline_new("test");
	
	source=gst_element_factory_make("v4l2src","play");
	
	flip=gst_element_factory_make("videoflip","flip");
	g_object_set(G_OBJECT(flip),"method",4,NULL);
	
	sink=gst_element_factory_make("xvimagesink","sink");
	
	if (!pipeline || !source || !sink ) {
		g_critical("Internal error\n");
		return NULL;
	}

   gst_bus_add_watch(gst_pipeline_get_bus(GST_PIPELINE(pipeline)),(GstBusFunc) bus_call, area);	
	gst_bin_add_many(GST_BIN(pipeline),source,flip,sink,NULL);
	caps=gst_caps_new_simple("video/x-raw-yuv",
		"width",G_TYPE_INT,width,
		"height",G_TYPE_INT,height,
		"framerate",GST_TYPE_FRACTION,30,1,
		NULL);
	gst_element_link_filtered(source,flip,caps);
	gst_element_link(flip,sink);
	gst_caps_unref(caps);
	return pipeline;
}

int
main(int argc,char *argv[]) {
	GError *error=NULL;
	GtkWidget *window;
	GtkWidget *area;
	GstElement *pipeline;
	gint width,height;
	
	gst_init(&argc,&argv);
	gtk_init(&argc,&argv);
	width=800;
	height=600;
	if (argc==3) {
		width=atoi(argv[1]);
		height=atoi(argv[2]);
	}
	if (width<100 || height<100 || width>1920 || height>1080) {
		g_error("args");
		exit(1);
	}	
	window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
	gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
	
	area=gtk_drawing_area_new();
	gtk_widget_set_size_request(area,width,height);
	
	gtk_container_add(GTK_CONTAINER(window),area);

	g_signal_connect(G_OBJECT(window),"destroy",G_CALLBACK(destroy),NULL);

	pipeline=create_pipeline(area,width,height);

	gtk_widget_show_all(window);
	gst_element_set_state(pipeline, GST_STATE_PLAYING);

	gtk_main();

	return(0);
}

